/*
 *
 * author:dustin
 * email:dushaobindoudou@gmail.com
 *
 * 调配用的，不同浏览器加载不同的css，不同的js
 *
 * 不赞同所有用到的js同时都加载过来，要针对不同浏览器器写不同的js，yui的进化版
 *
 * 队列 [{url:"js资源地址",success:"成功回调",error:"出错回调"}]
 *
 * todo:加载错误通知，需要修正
 *
 * todo:delete all loaded script
 *
 * todo:DomReady：beginLoad
 *
 * todo:Delay image、css
 * todo: css 不适用
 *
 */
!(function(win){
   
    var doc = win.document;
    var head = doc.getElementsByTagName("head")[0];
    var userAgent = navigator.userAgent.toLowerCase();
    var browser = {
        version: (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1],
        safari: /webkit/.test(userAgent),
        opera: /opera/.test(userAgent),
        msie: (/msie/.test(userAgent)) && (!/opera/.test(userAgent)),
        mozilla: (/mozilla/.test(userAgent)) && (!/(compatible|webkit)/.test(userAgent))
    };
    var addDomReadyCallback = (function(){
        // Everything that has to do with properly supporting our document ready event. Brought over from the most awesome jQuery. 
        var userAgent = navigator.userAgent.toLowerCase();
        // Figure out what browser is being used
        
        var readyBound = false;
        var isReady = false;
        var readyList = [];
        // Handle when the DOM is ready
        function domReady(){
            // Make sure that the DOM is not already loaded
            if (!isReady) {
                // Remember that the DOM is ready
                isReady = true;
                if (readyList) {
                    for (var fn = 0; fn < readyList.length; fn++) {
                        readyList[fn].call(window, []);
                    }
                    readyList = [];
                }
            }
        };
        
        // From Simon Willison. A safe way to fire onload w/o screwing up everyone else.
        function addLoadEvent(func){
            var oldonload = window.onload;
            if (typeof window.onload != 'function') {
                window.onload = func;
            }
            else {
                window.onload = function(){
                    if (oldonload) {
                        oldonload();
                    }
                    func();
                }
            }
        };
        // does the heavy work of working through the browsers idiosyncracies (let's call them that) to hook onload.
        function bindReady(){
            if (readyBound) {
                return;
            }
            readyBound = true;
            // Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
            if (document.addEventListener && !browser.opera) {
                // Use the handy event callback
                document.addEventListener("DOMContentLoaded", domReady, false);
            }
            // If IE is used and is not in a frame
            // Continually check to see if the document is ready
            if (browser.msie && window == top) 
                (function(){
                    if (isReady) 
                        return;
                    try {
                        // If IE is used, use the trick by Diego Perini
                        // http://javascript.nwbox.com/IEContentLoaded/
                        document.documentElement.doScroll("left");
                    } 
                    catch (error) {
                        setTimeout(arguments.callee, 0);
                        return;
                    }
                    // and execute any waiting functions
                    domReady();
                })();
            if (browser.opera) {
                document.addEventListener("DOMContentLoaded", function(){
                    if (isReady) 
                        return;
                    for (var i = 0; i < document.styleSheets.length; i++) 
                        if (document.styleSheets[i].disabled) {
                            setTimeout(arguments.callee, 0);
                            return;
                        }
                    // and execute any waiting functions
                    domReady();
                }, false);
            }
            if (browser.safari) {
                var numStyles;
                (function(){
                    if (isReady) 
                        return;
                    if (document.readyState != "loaded" && document.readyState != "complete") {
                        setTimeout(arguments.callee, 0);
                        return;
                    }
                    if (numStyles === undefined) {
                        var links = document.getElementsByTagName("link");
                        for (var i = 0; i < links.length; i++) {
                            if (links[i].getAttribute('rel') == 'stylesheet') {
                                numStyles++;
                            }
                        }
                        var styles = document.getElementsByTagName("style");
                        numStyles += styles.length;
                    }
                    if (document.styleSheets.length != numStyles) {
                        setTimeout(arguments.callee, 0);
                        return;
                    }
                    // and execute any waiting functions
                    domReady();
                })();
            }
            // A fallback to window.onload, that will always work
            addLoadEvent(domReady);
        };
        bindReady();
        // This is the public function that people can use to hook up ready.
        return function(fn, args){
            // Attach the listeners
            bindReady();
            // If the DOM is already ready
            if (isReady) {
                // Execute the function immediately
                fn.call(window, []);
            }
            else {
                // Add the function to the wait list
                readyList.push(function(){
                    return fn.call(window, []);
                });
            }
        };
    })();
    
    var Loader = function(){
        this.quene = [];
        this.async = "async";
        this.allLoaded = function(){
        };
        this.loadedQueueInfo = [];//{errorCount:"",loadedCount:"",queueLength:""}
        this.queneCount = this.quene.length;
        this.loaded = 0;
        this.tempCallback = function(){
        };
    }
    
    Loader.prototype = {
        constructor: Loader,
        init: function(quene, callback){
            var that = this;
            that.quene = quene || [];
            that.allLoaded = function(){
                this.tempCallback.call(that);
                this.mutinQueneLoad.call(that);
                //callback.apply(that, arguments);
            };
            addDomReadyCallback(function(){
                that.mutinQueneLoad.apply(that, []);
            });
        },
        createScript: function(url, success, error){
            var script = doc.createElement("script");
            var complete = false;
            var callback = success ||
            function(){
            };
			error = error || function(){};
			
			if("onerror" in script){
				script.onerror = error
			}
            if ("onload" in script) {
                script.onload = callback;
            }
            else {
                script.onreadystatechange = function(){
                    if (!complete && (!this.readyState || this.readyState === 'complete' || (this.readyState === 'loaded'))) {
                        if (!this.nextSibling) {
                            //console.log(this.nextSibling + " id");
							error();
                        }
                        complete = true;
                        callback();
                        script.onreadystatechange = null;
                    }
                    else {
                    
                    }
                }
            }
			
            script["type"] = "text/javascript";
            script["charset"] = "utf-8";
            script["src"] = url;
            script["async"] = this.async;
            return script;
        },
        createCSS: function(url, callback){
            var lk = doc.createElement("link");
            var complete = false;
            callback = callback ||
            function(){
            }
            
            if ("onload" in lk) {
                lk.onload = callback;
            }
            else {
                lk.onreadystatechange = function(){
                    if (!complete && (!this.readyState || this.readyState === 'complete' || (this.readyState === 'loaded'))) {
                        complete = true;
                        callback();
                        script.onreadystatechange = null;
                    }
                }
            }
            
            lk["type"] = "text/css";
            lk["rel"] = "stylesheet";
            lk["charset"] = "utf-8";
            lk["href"] = url;
            return lk;
        },
        appendScript: function(one){
            var that = this;
            if (!one) {
                return;
            }
            //var head = doc.getElementsByTagName("head")[0];
			var currentQueue = that.loadedQueueInfo[that.loadedQueueInfo.length - 1];
            head.appendChild(this.createScript(one.url, function(){               
                currentQueue.loadedCount++;
                if (currentQueue.loadedCount >= currentQueue.queueLength) {
                    that.allLoaded();
                }
                if (one.callback) {
                    one.callback();
                }
            },function(){
				currentQueue.errorCount++;				
			}));
        },
        appendCss: function(one){
            var that = this;
            if (!one) {
                return;
            }
            head.appendChild(this.createCss(one.url, function(){
                that.loaded++;
                if (that.loaded >= that.queneCount) {
                    that.allLoaded();
                }
                if (one.callback) {
                    one.callback();
                }
            }));
        },
        appendAsync: function(one){
            var that = this;
            if (!one) {
                return;
            }
            var fl;
            switch (one.type) {
                case "css":
                    fl = this.createCSS(one.url, function(){
                        that.loaded++;
                        if (that.loaded >= that.queneCount) {
                            that.allLoaded();
                        }
                        if (one.callback) 
                            one.callback();
                        that.appendAsync(that.quene.shift());
                    });
                    break;
                case "js":
                    fl = this.createScript(one.url, function(){
                        that.loaded++;
                        if (that.loaded >= that.queneCount) {
                            that.allLoaded();
                        }
                        if (one.callback) 
                            one.callback();
                        that.appendAsync(that.quene.shift());
                    });
                    break;
                default:
                    break;
            }
            head.appendChild(fl);
        },
        loading: function(){
            var i = 0, len = this.quene.length, that = this;
            if (this.async) {
                for (; i < len; i++) {
                    var one = this.quene.shift();
                    if (one) {
                        switch (one.type) {
                            case "css":
                                that.appendCss();
                                break;
                            case "js":
                                that.appendScript(one);
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
            else {
                var one = this.quene.shift();
                that.appendAsync(one);
            }
        },
        mutinQueneLoad: function(){
            var that = this;
            var toBeLoadedObj = that.quene.shift();
            if (!toBeLoadedObj) {
                return;
            }
            var toLoadQueue = toBeLoadedObj.queue, i = 0, len = toLoadQueue.length;
            that.tempCallback = toBeLoadedObj.callback ||
            function(){
            };
            that.loadedQueueInfo.push({
                queueLength: toLoadQueue.length,
                loadedCount: 0,
                errorCount: 0
            });
            for (; i < len; i++) {
                var one = toLoadQueue.shift();
                if (one) {
                    switch (one.type) {
                        case "css":
                            that.appendCss();
                            break;
                        case "js":
                            that.appendScript(one);
                            break;
                        default:
                            break;
                    }
                }
            }
        }
    }
    win.vRequire = function(){
        var ld = new Loader();
        return ld.init.apply(ld, arguments);
    }
})(window)
